package net.hserver.gateway.core;

import cn.hserver.core.ioc.IocUtil;
import cn.hserver.core.ioc.annotation.Autowired;
import cn.hserver.core.ioc.annotation.Bean;
import cn.hserver.plugin.gateway.business.BusinessHttp7;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.AttributeKey;
import net.hserver.gateway.core.bean.Proxy;
import net.hserver.gateway.core.exception.GateWayException;
import net.hserver.gateway.core.node.ServerNodeManager;

import java.net.SocketAddress;

@Bean
public class Http7 extends BusinessHttp7 {

    @Autowired
    private GateWayOut gateWayOut;

    private final AttributeKey<Proxy> PROXY_ATTRIBUTE_KEY = AttributeKey.valueOf("proxyInfo");

    @Override
    public Object in(ChannelHandlerContext ctx, Object msg) {
        if (msg instanceof FullHttpRequest) {
            Proxy proxy = ProxyHandler.builder(ctx,msg, new Proxy());
            ProxyHandler.proxyInfo(proxy);
            ProxyHandler.statistics(proxy);
            ctx.channel().attr(PROXY_ATTRIBUTE_KEY).set(proxy);
            if (proxy.getServerNode() == null) {
                gateWayOut.out(new GateWayException(HttpResponseStatus.SERVICE_UNAVAILABLE, "拒绝访问"), proxy);
                return null;
            }else {
                FullHttpRequest fullHttpRequest = (FullHttpRequest) msg;
                HttpHeaders headers = fullHttpRequest.headers();
                headers.set("Host", proxy.getServerNode().getInetSocketAddress().getHostString());
            }
        }
        return msg;
    }

    @Override
    public SocketAddress getProxyHost(ChannelHandlerContext ctx, Object fullHttpRequest, SocketAddress sourceSocketAddress) {
        Proxy proxy = ctx.channel().attr(PROXY_ATTRIBUTE_KEY).get();
        return proxy.getServerNode().getInetSocketAddress();
    }

    @Override
    public Object out(Channel channel, Object obj) {
        return obj;
    }

    @Override
    public boolean connectController(ChannelHandlerContext ctx, boolean connectResult, int connectNum, Throwable error) {
        Proxy proxy = ctx.channel().attr(PROXY_ATTRIBUTE_KEY).get();
        if (connectResult) {
            IocUtil.getBean(ServerNodeManager.class).addConnect(proxy.getServerNode().getRouterId(), proxy.getServerNode().getNodeId());
        } else {
            if (connectNum > proxy.getServerNode().getErrorNum()) {
                /**
                 * 对当前节点打标，标识程序不健康哦.
                 */
                IocUtil.getBean(ServerNodeManager.class).markUnhealthy(proxy.getServerNode().getRouterId(), proxy.getServerNode().getNodeId());
                //检查备用服务器，替换上线.

                //输出相关错误数据
                IocUtil.getBean(GateWayOut.class).out(new GateWayException(HttpResponseStatus.GATEWAY_TIMEOUT, "网关连接远端服务器超时", error), proxy);
            } else {
                return true;
            }
        }
        return false;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        Proxy proxy = ctx.channel().attr(PROXY_ATTRIBUTE_KEY).get();
        gateWayOut.out(new GateWayException(HttpResponseStatus.SERVICE_UNAVAILABLE, "网关异常", cause), proxy);
    }
}